package com.elric.mall.common.utils;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 实现功能：本地线程变量通用方法
 *
 * @author 作者[Yuxuan.he]
 * @version 1.0.00  2021-11-10 15:21
 */
public final class ThreadLocalUtil {

    /**
     * 开始使用前调用
     */
    public static void begin() {
        ThreadLocalHolder.begin();
    }

    /**
     * 使用结束后调用
     */
    public static void end() {
        ThreadLocalHolder.end();
    }

    /**
     * 是否有效
     */
    public static boolean isAvailable() {
        return Objects.nonNull(ThreadLocalHolder.LOCAL_VAR.get());
    }

    /**
     * 读本地线程变量
     */
    public static <T> T getLocalVar(String key) {
        return get(key);
    }

    /**
     * 写本地线程变量
     */
    public static void setLocalVar(String key, Object value) {
        set(key, value);
    }

    /**
     * 删本地线程变量
     */
    public static void removeLocalVar(String key) {
        remove(key);
    }

    @SuppressWarnings("unchecked")
    private static <T> T get(String key) {
        Map<String, Object> map = ThreadLocalHolder.LOCAL_VAR.get();
        if (Objects.isNull(map)) {
            return null;
        }
        return (T) map.get(key);
    }

    private static void set(String key, Object value) {
        Map<String, Object> map = ThreadLocalHolder.LOCAL_VAR.get();
        if (Objects.isNull(map)) {
            return;
        }
        map.put(key, value);
    }

    private static void remove(String key) {
        Map<String, Object> map = ThreadLocalHolder.LOCAL_VAR.get();
        if (Objects.isNull(map)) {
            return;
        }
        map.remove(key);
    }

    private static final class ThreadLocalHolder {

        /**
         * 临时缓存线程变量
         */
        private static final ThreadLocal<Map<String, Object>> LOCAL_VAR = new ThreadLocal<>();

        public static void begin() {
            if (Objects.isNull(LOCAL_VAR.get())) {
                LOCAL_VAR.set(new HashMap<>(16));
            }
        }

        public static void end() {
            LOCAL_VAR.remove();
        }
    }
}